home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
aminet
/
util
/
misc
/
zkick301.lzh
/
zkick.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-10
|
10KB
|
531 lines
/*
ZKick V3.01 -- Copyright (C) 1991 by Daniel Zenchelsky
This program may be freely copied, as long as all copyright
notices are left intact and unchanged.
*/
#include <stdio.h>
#include "zkick.h"
#include <libraries/configvars.h>
#include <libraries/expansion.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/tasks.h>
#include <exec/execbase.h>
#define BUFSIZE (64*1024)
#define KICKSIZE (512*1024)
#define NUMBUFS (KICKSIZE/BUFSIZE)
#define STARTKICK (void *)0x200000
#define STACK_SIZE 1024
#define BOGUSMMU 0xffffffffL
#define IFDEBUG if (DEBUG) {
#define ENDIFDEBUG }
#define USAGE1 "Usage: ZKick [-start <hex address>] [-debug] [-die] [-mmu]\n"
#define USAGE2 " [-noreset] [-nochecksum] [-print] [-c0] KickFile\n"
/* For the Assembly routines to use: */
long NumBufs=NUMBUFS;
ULONG BufSize=BUFSIZE;
ULONG EndKick;
extern ULONG StartKick;
APTR stack = NULL;
struct Task *tc = NULL;
char *taskname = "Zkick Task";
struct ExpansionBase *ExpansionBase=NULL;
struct ExecBase *ExecBase=NULL;
void main();
void cleanup();
void DoAddCD();
void GetMem();
void KickLoad();
void StartTask();
extern void KickCopy();
extern void MakeRomTag();
extern long GetCPUType();
extern long GetMMUType();
extern long connum;
extern struct ConfigDev config[8];
extern long memnum;
extern ULONG memory[8][2];
extern long Survive;
extern long MMU;
extern long NOMMU;
extern long NORESET;
extern long NOCHECKSUM;
extern long DEBUG;
extern long PRINT;
extern long LOADC0;
extern long V175;
long CPU;
int CXBRK(void) { return(0); }
void *MemArray[NUMBUFS];
void main(argc,argv)
int argc;
char *argv[];
{
struct ConfigDev *MyConfigDev;
char *kickfile;
printf("ZKick V3.01 Copyright (C) 1991 by Daniel Zenchelsky\n");
printf("---------------------------------------------------\n");
printf(" This program may be freely copied, as long\n");
printf(" as all copyright notices are left intact.\n\n");
ExpansionBase= (struct ExpansionBase *)OpenLibrary( EXPANSIONNAME,0);
if(ExpansionBase==NULL)
{
printf("Error opening expansion library!!\n");
cleanup();
}
ExecBase= (struct ExecBase *)OpenLibrary("exec.library",0);
if(ExecBase==NULL)
{
printf("Error opening Exec library!!\n");
cleanup();
}
if (ExecBase->LibNode.lib_Version<33 || ExecBase->LibNode.lib_Version>34)
{
printf("ZKick will only run under Kickstart 1.2/1.3\n");
cleanup();
}
connum=0;
argv++;
argc--;
Survive=1;
NOMMU=1;
StartKick=0x200000;
if (argc<1)
{
printf(USAGE1);
printf(USAGE2);
cleanup();
}
while(argc>1)
{
if (argv[0][0]!='-')
{
printf(USAGE1);
printf(USAGE2);
cleanup();
}
if (strcmp("-die",argv[0])==0)
{
IFDEBUG
printf("-die\n");
ENDIFDEBUG
Survive=0;
}
if (strcmp("-mmu",argv[0])==0)
{
IFDEBUG
printf("-mmu\n");
ENDIFDEBUG
NOMMU=0;
}
if (strcmp("-noreset",argv[0])==0)
{
IFDEBUG
printf("-noreset\n");
ENDIFDEBUG
NORESET=1;
}
if (strcmp("-nochecksum",argv[0])==0)
{
IFDEBUG
printf("-nochecksum\n");
ENDIFDEBUG
NOCHECKSUM=1;
}
if (strcmp("-start",argv[0])==0)
{
sscanf(argv[1]," %x",&StartKick);
IFDEBUG
printf("-start %x\n",StartKick);
ENDIFDEBUG
if (StartKick<0x200000)
{
printf("Can't put kickstart in CHIP ram.\n");
cleanup();
}
if (V175==0)
{
printf("-start only works with Kickstart 37.175, see docs\n");
cleanup();
}
argv++;
argc--;
}
if (strcmp("-debug",argv[0])==0)
{
printf("-debug\n");
DEBUG=1;
}
if (strcmp("-print",argv[0])==0)
{
IFDEBUG
printf("-print\n");
ENDIFDEBUG
PRINT=1;
}
if (strcmp("-c0",argv[0])==0)
{
IFDEBUG
printf("-c0\n");
ENDIFDEBUG
if (V175==0)
{
printf("-c0 only works with Kickstart 37.175, see docs\n");
cleanup();
}
if (((ULONG)ExecBase&0xFFFF0000)==0x00C00000)
{
printf("ExecBase is in $C00000 memory.\n");
printf("Run NoC0Ram before using ZKick.\n");
cleanup();
}
LOADC0=1;
StartKick=0x00C00000;
}
if (strcmp("-v175",argv[0])==0)
{
IFDEBUG
printf("-v175\n");
ENDIFDEBUG
V175=1;
printf("Kickstart relocation enabled. Be sure you are using V37.175!\n");
}
argv++;
argc--;
}
kickfile=argv[0];
EndKick=StartKick+KICKSIZE-1;
if((stack = (APTR) AllocMem(STACK_SIZE, MEMF_CHIP | MEMF_CLEAR)) == NULL)
{
printf("Not enough memory for task stack\n");
cleanup();
}
if ((tc = (struct Task *)
AllocMem(sizeof(struct Task),MEMF_CHIP | MEMF_CLEAR | MEMF_PUBLIC)) == NULL)
{
printf("Not enough memory for task structure\n");
cleanup();
}
if (LOADC0==0 && CheckForMem()==-1)
{
printf("You must have a 512k or greater memory board at $%x.\n",StartKick);
cleanup();
}
MyConfigDev=NULL;
MyConfigDev=FindConfigDev(NULL,-1,-1);
if(MyConfigDev==NULL) printf("No configured devices found\n");
else DoAddCD(MyConfigDev);
while((MyConfigDev=FindConfigDev(MyConfigDev,-1,-1))!=NULL)
{
DoAddCD(MyConfigDev);
}
printf("Found %d expansion devices, and %d memory boards.\n",connum,memnum);
if (NOMMU==0)
{
CPU=GetCPUType();
MMU=GetMMUType();
if (MMU==BOGUSMMU) MMU=0;
IFDEBUG
printf("CPU: %d, MMU: %d\n",CPU,MMU);
ENDIFDEBUG
}
if (LOADC0==0) GetMem();
KickLoad(kickfile);
MakeRomTag();
printf("Rebooting in 5 seconds...\n");
Delay(50*5);
StartTask();
Wait(0L); /* Hang around forever (not very long, actually.) */
}
void cleanup()
{
if(tc) FreeMem((void *)tc,sizeof(struct Task));
if(stack) FreeMem((void *)stack,(ULONG)STACK_SIZE);
if(ExpansionBase) CloseLibrary(ExpansionBase);
if(ExecBase) CloseLibrary(ExecBase);
exit(0);
}
void DoAddCD(dev)
struct ConfigDev *dev;
{
if ((dev->cd_Rom.er_Type & ERTF_MEMLIST) == 0)
{
if (connum<8)
{
config[connum]=*dev;
config[connum].cd_Rom.er_Reserved0c=0;
config[connum].cd_Rom.er_Reserved0d=0;
config[connum].cd_Rom.er_Reserved0e=0;
config[connum].cd_Rom.er_Reserved0f=0;
config[connum].cd_Flags |= CDF_CONFIGME;
config[connum].cd_Driver=NULL;
connum++;
IFDEBUG
printf("Adding board at $%x to list.\n",(ULONG)(dev->cd_BoardAddr));
ENDIFDEBUG
}
else
{
printf("Too many expansion boards!\n");
cleanup();
}
}
else
{
if (memnum<7)
{
ULONG start,len,end;
start=(ULONG)dev->cd_BoardAddr;
len=(ULONG)dev->cd_BoardSize;
end=start+len-1;
if ((INTERSECT(StartKick,EndKick,start,end) && !SUBSET(StartKick,EndKick,start,end)) || SUPERSET(StartKick,EndKick,start,end))
{
printf("Kickstart memory can not span multiple memory boards!\n");
cleanup();
}
if (SUBSET(StartKick,EndKick,start,end) || EQUAL(StartKick,EndKick,start,end))
{
if (start<StartKick)
{
memory[memnum][0]=start;
memory[memnum][1]=StartKick-start;
IFDEBUG
printf("Adding memory at $%x, size $%x to list.\n",
memory[memnum][0],memory[memnum][1]);
ENDIFDEBUG
memnum++;
}
if (end>EndKick)
{
memory[memnum][0]=EndKick+1;
memory[memnum][1]=end-EndKick;
IFDEBUG
printf("Adding memory at $%x, size $%x to list.\n",
memory[memnum][0],memory[memnum][1]);
ENDIFDEBUG
memnum++;
}
}
else
{
memory[memnum][0]=start;
memory[memnum][1]=len;
memnum++;
}
}
else
{
printf("Too many memory boards!\n");
cleanup();
}
}
}
/* Allocate NUMBUFS (8) buffers of size BUFSIZE (64k) _NOT_ within the final
KickStart address region.
*/
void GetMem()
{
int BufNum,BadNum=0,x;
void *MemBad[NUMBUFS];
for (BufNum=0;BufNum<NUMBUFS;BufNum++)
{
MemArray[BufNum]=(void *)AllocMem(BUFSIZE,0);
while (MemArray[BufNum]!=(void *)NULL &&
!ABOVE((ULONG)MemArray[BufNum],(ULONG)MemArray[BufNum]+BUFSIZE-1,StartKick,EndKick) &&
!BELOW((ULONG)MemArray[BufNum],(ULONG)MemArray[BufNum]+BUFSIZE-1,StartKick,EndKick))
{
MemBad[BadNum++]=MemArray[BufNum];
IFDEBUG
printf("* UNUSED * Memory allocated at location $%x\n",(ULONG)MemBad[BadNum-1]);
ENDIFDEBUG
MemArray[BufNum]=(void *)AllocMem(BUFSIZE,0);
}
if (MemArray[BufNum]==(void *)NULL)
{
if (BufNum>0)
for (x=0;x<BufNum-1;x++) FreeMem(MemArray[x],BUFSIZE);
if (BadNum>0)
for (x=0;x<BadNum-1;x++) FreeMem(MemBad[x],BUFSIZE);
printf("Couldn't allocate memory.\n");
cleanup();
}
IFDEBUG
printf("Memory allocated at location $%x\n",(ULONG)MemArray[BufNum]);
ENDIFDEBUG
}
/* Free memory that was allocated inside KickStart area */
if (BadNum>0)
for (x=0;x<BadNum-1;x++) FreeMem(MemBad[x],BUFSIZE);
}
void KickLoad(filename)
char filename[];
{
int BufNum;
int file;
file=open(filename,0);
if (file==-1)
{
printf("Error opening %s\n",filename);
for (BufNum=0;BufNum<NUMBUFS;BufNum++) FreeMem(MemArray[BufNum],(ULONG)BUFSIZE);
close(filename);
cleanup();
}
lseek(file,8,0);
if (LOADC0!=0)
{
IFDEBUG
printf("Loading Kickstart @ %08x\n",StartKick);
ENDIFDEBUG
if (read(file,(void *)StartKick,KICKSIZE)!=KICKSIZE)
{
printf("Error reading %s\n",filename);
for (BufNum=0;BufNum<NUMBUFS;BufNum++) FreeMem(MemArray[BufNum],(ULONG)BUFSIZE);
close(filename);
cleanup();
}
}
else
{
for (BufNum=0;BufNum<NUMBUFS;BufNum++)
{
IFDEBUG
printf("Reading %d\n",BufNum*BUFSIZE);
ENDIFDEBUG
if (read(file,MemArray[BufNum],BUFSIZE)!=BUFSIZE)
{
printf("Error reading %s\n",filename);
for (BufNum=0;BufNum<NUMBUFS;BufNum++) FreeMem(MemArray[BufNum],(ULONG)BUFSIZE);
close(filename);
cleanup();
}
}
}
}
void StartTask()
{
/* Initialize necessary fields, others were cleared by MEMF_CLEAR */
tc->tc_Node.ln_Type = NT_TASK;
tc->tc_Node.ln_Name = taskname;
tc->tc_SPLower = (APTR)stack;
tc->tc_SPUpper = (APTR)(STACK_SIZE + (ULONG)stack);
tc->tc_SPReg = tc->tc_SPUpper;
AddTask(tc, KickCopy, 0L);
}
#define FUDGEFACTOR 64 /* Fudge factor for MemHeader */
CheckForMem()
{
struct MemHeader *mem;
BOOL flag=FALSE;
Forbid();
for (mem = (struct MemHeader *)ExecBase->MemList.lh_Head;
mem->mh_Node.ln_Succ;
mem = (struct MemHeader *)mem->mh_Node.ln_Succ)
{
if (((ULONG) (mem->mh_Lower - FUDGEFACTOR ) <= StartKick) && ((ULONG) mem->mh_Upper >= EndKick))
flag=TRUE;
}
Permit();
if (flag==TRUE) return(0);
else return(-1);
}